package common

import (
	"gitee.com/jamon/espoir_go/logger"
	"time"
)

type SerializeController struct {
	// 用于将多个协程触发的操作 放到同一个协程中执行，避免多个协程同时操作同一个资源
	serializeChan chan func()
	IsStop        bool
}

func NewSerializeController(MaxChannelNum int32) *SerializeController {
	ctl := &SerializeController{
		serializeChan: make(chan func(), MaxChannelNum),
	}
	go SafeRun(func() {
		ctl.Run()
	})
	return ctl
}

func (sc *SerializeController) Execute(f func(), funcDesc string) {
	defer func() {
		logger.Debug("func execute in session goroutine", logger.Kwargs{"func": funcDesc})
	}()
	sc.serializeChan <- f
}

func (sc *SerializeController) ExecuteWithTimeout(f func(), funcDesc string) {
	select {
	case sc.serializeChan <- f:
		return
	case <-time.After(time.Second * 2):
		logger.Error("add func execute in session goroutine timeout", logger.Kwargs{"func": funcDesc})
	}
}

func (sc *SerializeController) Run() {
	for {
		if sc.IsStop {
			break
		}
		select {
		case f := <-sc.serializeChan:
			f()
		}
	}
}

func (sc *SerializeController) Quit() {
	close(sc.serializeChan)
}
